package config

import (
	"bytes"
	"fmt"
	"net"
	"os"
	"path/filepath"
	"smart-flow/monitor/logger"

	"github.com/google/uuid"
	"go.uber.org/zap"
)

type Endpoints struct {
	InfoUrl    string
	LoginUrl   string
	AliveUrl   string
	DownUrl    string
	ProveV6Url string
}

type BandwidthLimit struct {
	MaxDownTotalV4 int64
	MaxDownTotalV6 int64
	MaxDownTotal   int64
}

type PusherEndpoints struct {
	InfoUrl  string
	LoginUrl string
	AliveUrl string
	DownUrl  string
	StatIps  []string
}

var (
	MachineId           string
	IpAddr              string
	EndpointsInfo       Endpoints
	BandwidthLimitInfo  BandwidthLimit
	PusherEndpointsInfo PusherEndpoints
)

func InitRuntime() {
	var err error
	MachineId, err = getMachineId()
	if err != nil {
		os.Exit(1)
	}
	IpAddr = getIpAddr()
	if IpAddr == "" {
		os.Exit(1)
	}
	EndpointsInfo = getEndpoints()
	PusherEndpointsInfo = getPusherEndpoints()
	BandwidthLimitInfo = getBandwidthLimit()
}

func getMachineId() (string, error) {
	dir := filepath.Dir(AppConfig().Monitor.MachineIdFile)
	if dir != "" && dir != "." {
		if err := os.MkdirAll(dir, 0755); err != nil {
			return "", fmt.Errorf("创建目录失败, 异常信息: %w", err)
		}
	}
	data, err := os.ReadFile(AppConfig().Monitor.MachineIdFile)
	if err == nil {
		id := string(bytes.TrimSpace(data))
		if _, parseErr := uuid.Parse(id); parseErr == nil {
			logger.Logger.Info("[管控] 加载机器编码", zap.String("machineId", id))
			return id, nil
		}
		logger.Logger.Warn("[管控] 机器编码格式不正确", zap.String("machineId", id))
	} else if !os.IsNotExist(err) {
		logger.Logger.Warn("[管控] 机器编码加载异常", zap.Error(err))
	} else {
		logger.Logger.Info("[管控] 机器编码不存在")
	}
	newId := uuid.New().String()
	err = os.WriteFile(AppConfig().Monitor.MachineIdFile, []byte(newId), 0644)
	if err != nil {
		return "", fmt.Errorf("保存机器编码失败. 异常信息: %w", err)
	}
	logger.Logger.Info("[管控] 创建新的机器编码", zap.String("machineId", newId))
	return newId, nil
}

func getIpAddr() string {
	iFace, err := net.InterfaceByName(AppConfig().Monitor.InterfaceName)
	if err != nil {
		logger.Logger.Error("[管控] 获取机器IP异常", zap.String("interfaceName", AppConfig().Monitor.InterfaceName), zap.Error(err))
		return ""
	}
	addresses, err := iFace.Addrs()
	if err != nil {
		logger.Logger.Error("[管控] 获取机器IP异常", zap.String("interfaceName", AppConfig().Monitor.InterfaceName), zap.Error(err))
		return ""
	}
	for _, addr := range addresses {
		ipNet, ok := addr.(*net.IPNet)
		if ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil {
			return ipNet.IP.String()
		}
	}
	logger.Logger.Error("[管控] 未找到有效的 IPv4 地址", zap.String("interfaceName", AppConfig().Monitor.InterfaceName))
	return ""
}

func getEndpoints() Endpoints {
	var proveV6Url string
	if AppConfig().Monitor.ProverV6 != "" {
		proveV6Url = fmt.Sprintf("http://%s:%d%s", AppConfig().Monitor.ProverV6, HttpManagePort, PathAgentInfo)
	}
	return Endpoints{
		InfoUrl:    fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathAgentInfo),
		LoginUrl:   fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathAgentLogin),
		AliveUrl:   fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathAgentAlive),
		DownUrl:    fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathDownload),
		ProveV6Url: proveV6Url,
	}
}

func getPusherEndpoints() PusherEndpoints {
	statIps := AppConfig().Stat.Ips
	if len(statIps) == 0 {
		statIps = append(statIps, IpAddr)
	}
	return PusherEndpoints{
		InfoUrl:  fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathPusherInfo),
		LoginUrl: fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathPusherLogin),
		AliveUrl: fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathPusherAlive),
		DownUrl:  fmt.Sprintf("http://%s:%d%s", IpAddr, HttpManagePort, PathDownload),
		StatIps:  statIps,
	}
}

func getBandwidthLimit() BandwidthLimit {
	return BandwidthLimit{
		MaxDownTotalV4: AppConfig().Dy.MaxDownTotalV4 * MBit,
		MaxDownTotalV6: AppConfig().Dy.MaxDownTotalV6 * MBit,
		MaxDownTotal:   AppConfig().Dy.MaxDownTotal * MBit,
	}
}
